#coding:utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')

import os

import paramiko

import dbs

class SSH(object):
    """docstring for SSH"""
    def __init__(self):
        super(SSH, self).__init__()
        self.client = paramiko.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    """执行命令"""
    def execute(self, command, host_info):
        '''
        args : 
            command : 执行的命令
            host_info : 传入主机的连接信息 ('192.168.100.50', 22, 'root', '***')
        '''
        try: 
            self.ssh_connect(host_info=host_info)
            stdin, stdout, stderr = self.client.exec_command(command)
            err = stderr.read()
            if not err:
                content = stdout.read()
                result = {
                    'code' : 0,
                    'message' : 'success',
                    'data' : content
                }
                return result
            result = {
                'code' : 500,
                'message' : err
            }
            return result

        except Exception as e:
            result = {
                'code' : 520,
                'message' : str(e)
            }
            return result
        

    """批量执行命令"""
    def mult_execute(self, command):
        '''
        args : 
            command : 批量执行的命令
        warring: 
            注意，这是自动获取批量主机信息。
        '''
        result = {}
        data = self.get_hosts()
        if data.get('code') != 0:
            return data
        hosts_info = data['hosts']
        for host_info in hosts_info:
            data = self.execute(command, host_info)
            result[host_info[0]] = data #主机=主机执行命令结果
        return result 

    """上传文件"""
    def upload(self, lpath, rpath, host_info):
        '''
        args: 
            lpath : 本地要上传的文件绝对路径
            rpath : 远程的文件绝对路径
            host_info : 传入主机的执行信息
        '''
        try:
            self.ssh_connect(host_info)
            sftp = self.client.open_sftp()
            try:
                #put(localpath, remotepath)
                sftp.put(lpath, rpath)
                return {'code' : 0, 'message' : 'upload success'}
            except Exception as e: #sftp的异常
                return { 'code' : 521, 'message' : str(e)}
        except Exception as e: #SSH连接的异常
            return {'code' : 520, 'message' : str(e)}
        

    """下载文件"""
    def download(self, rpath, lpath, host_info):
        '''
        args: 
            lpath : 本地要下载的文件绝对路径
            rpath : 远程的文件绝对路径
            host_info : 传入主机的执行信息
        '''
        try:
            self.ssh_connect(host_info)
            sftp = self.client.open_sftp()
            try:
                #put(localpath, remotepath)
                sftp.get(rpath, lpath)
                return {'code' : 0, 'message' : 'download success'}
            except Exception as e: #sftp的异常
                return { 'code' : 521, 'message' : str(e)}
        except Exception as e: #SSH连接的异常
            return {'code' : 520, 'message' : str(e)}

    """批量上传文件"""
    def mult_upload(self, lpath, rpath):
        '''
        args: 
            lpath : 本地要上传的文件绝对路径
            rpath : 远程的文件绝对路径
        wanning: 
            注意，这是自动获取批量主机信息。
        '''
        result = {}
        data = self.get_hosts()
        if data.get('code') != 0:
            return data
        hosts_info = data['hosts']
        for host_info in hosts_info:
            data = self.upload(rpath=rpath, lpath=lpath, host_info=host_info)
            result[host_info[0]] = data #主机=主机执行命令结果
        return result 

    """批量下载文件"""
    def mult_download(self, rpath, lpath):
        '''
        args: 
            lpath : 本地要下载的文件绝对路径
            rpath : 远程的文件绝对路径
        wanning: 
            注意，这是自动获取批量主机信息。
        '''
        result = {}
        data = self.get_hosts()
        if data.get('code') != 0:
            return data
        hosts_info = data['hosts']
        for host_info in hosts_info:
            hostname = host_info[0]
            #处理文件名
            dir, filename = os.path.split(lpath)
            filename = '{hostname}-{filename}'.format(hostname=hostname, filename=filename)
            xlpath = os.path.join(dir,filename) # 这是新的本地路径
            data = self.download(lpath=xlpath, rpath=rpath, host_info=host_info)
            result[hostname] = data #主机=主机执行命令结果
        return result 

    """获取主机信息"""
    def get_hosts(self, host=False):
        try:
            conn, cur = dbs.db_connect()
            if host:
                query = '''
                        SELECT 
                            hostname,port,username,password 
                        FROM 
                            host
                        WHERE hostname = '{host}'
                        '''.format(host=host)
            else:
                query = '''
                        SELECT hostname,port,username,password FROM host
                        '''
            cur.execute(query)
            if host:
                host = cur.fetchone()
                return { 'code' : 0, 'message' : 'success' ,'host':host}
            hosts = cur.fetchall()
            return { 'code' : 0 , 'message':'success', 'hosts' : hosts}
        except Exception as e:
            return { 'code' : 522 ,'message': str(e) }

    def ssh_connect(self, host_info):
        #把数据库查询格式转换成字典传参格式
        key = ('hostname', 'port', 'username', 'password')
        host_info = dict(zip(key,host_info))
        host_info['timeout'] = 3
        self.client.connect(**host_info)

    def view_hosts(self):
        conn, cur = dbs.db_connect()
        query = 'SELECT hostname FROM host'
        #(('192.168.100.50'),('192.168.100.51')...)
        cur.execute(query)
        data = cur.fetchall()
        hosts = [ hostname[0] for hostname in data ]
        return hosts

if __name__ == '__main__':
    '''
    s = SSH()
    host_info = s.get_hosts(host='192.168.100.50')['host']
    #lpath, rpath, host_info
    #result = s.execute('uptime', host_info=host_info)
    #result = s.upload('./tools.py','/tmp/tools.py', host_info=host_info)
    #result = s.download('/tmp/tools.py', './tools22.py', host_info=host_info)
    #result = s.mult_execute('uptime')
    #result = s.mult_download(rpath='/var/log/nginx/access.log', lpath='../../logs/access.log')
    result = s.mult_upload(rpath='/tmp/access.log', lpath='users.py')
    print result
    print s.view_hosts()
    '''

